import sys, os
import pygame
from pygame.locals import *
from utils import *
import collections
import StringIO
from time import sleep
import urllib2

class FrameBuffer():
    #===========================================================================
    # FrameBuffer - Class for interacting with the Framebuffer
    #===========================================================================
    
    # Constants
    # Colours
    BLACK = (  0,   0,   0)
    WHITE = (255, 255, 255)  
    topMenuList=["Now Playing","Artists","Albums","Playlists","Spotify","Radio","Settings","Exit"]
    
    def __init__(self, screenWidth=320, screenHeight=240):
        os.environ["SDL_FBDEV"] = "/dev/fb1"
        pygame.init()
        pygame.display.set_caption('Stream UI')
        pygame.mouse.set_visible(0)
        # set up the window
        self.screenWidth=screenWidth
        self.screenHeight=screenHeight
        self.screen = pygame.display.set_mode((self.screenWidth, self.screenHeight), 0, 32)
        self.background = pygame.Surface(self.screen.get_size())
        
        #Screen definitions
        self.screenType = []
        self.screenName = ''
        self.menuList=[]
        self.menuID=[]
        self.menuKey = ''
        self.topIndex = []
        self.selectedRow = []
        self.history = collections.defaultdict(dict)  
        self.nRows = 6        
        self.previousScreenType = ''
        self.previousScreenName = ''
        self.previousMenuKey = ''
        
        # Some positioning definitions 
        self.rowHeight = self.background.get_height()/self.nRows
        self.fontSize = 30
        self.font = pygame.font.Font(None, self.fontSize)     
        
    #def getMenuIndex(self):
    #    return self.menuTopRow+self.menuRow
    
    def saveScreenHistory(self):
        # Store current menu state in history
        # Check if current screen is a menu
        self.history[self.screenName]['screenType'] = self.screenType
        self.history[self.screenName]['previousScreenType'] = self.previousScreenType
        self.history[self.screenName]['previousScreenName'] = self.previousScreenName
        self.history[self.screenName]['previousMenuKey'] = self.previousMenuKey
        if self.screenType == 'menu':
            self.history[self.screenName]['menuKey'] = self.menuKey
            self.history[self.screenName]['topIndex'] = self.topIndex
            self.history[self.screenName]['selectedRow'] = self.selectedRow   
            
        #print "Stored %s in history" % self.screenName
    def drawNotificationScreen(self,string):
        self.saveScreenHistory()
        self.background.fill(self.WHITE)
        text = self.font.render(string,1,self.BLACK)        
        textpos = text.get_rect()
        textpos.centerx = self.background.get_rect().centerx
        textpos.centery = self.background.get_rect().centery
        self.background.blit(text,textpos)
        self.screen.blit(self.background, (0, 0))
        
        self.screenName = 'connecting'  
        self.screenType = 'info'
        self.updateDisplay()
        sleep(1)
        
    def drawSplash(self):
        string='T u t t i'
        self.background.fill(self.WHITE)
        #self.screen.blit(self.background, (0, 0))
        #box = pygame.draw.rect(self.background, self.BLACK ,(0, yPos, self.background.get_width(), self.rowHeight))
        myfont = pygame.font.SysFont("Abyssinica SIL", 50)
              
        text = myfont.render(string,1,self.BLACK)        
        textpos = text.get_rect()
        textpos.centerx = self.background.get_rect().centerx
        textpos.centery = self.background.get_rect().centery
               
        #img = pygame.image.load("piano.jpg")
        #img = pygame.transform.scale(img, (320,240)) 
        
        #imagerect = img.get_rect()
        #xOffset = (self.screenWidth-self.screenHeight)/2
        #self.background.blit(img, (0,28), imagerect)
        
        self.background.blit(text,textpos)
        self.screen.blit(self.background, (0, 0))
        
        self.updateDisplay()
        sleep(2)   
        nFadeFrames=30
        for x in range (0,nFadeFrames+1):            
            fadeVal = x*(255.0/nFadeFrames)
            text = myfont.render(string,1,(fadeVal,fadeVal,fadeVal)) 
            self.background.fill(self.WHITE)
            self.background.blit(text,textpos)
            self.screen.blit(self.background, (0, 0))
            self.updateDisplay()
            sleep(0.07)
        sleep(1)
        
    def setMenu(self,name,menuList,menuID,key):
        #=======================================================================
        # setMenu - sets the display menu
        #=======================================================================
        # Store the last state of the previous menu
        logging.debug(str("Setting menu: "+ name))
        self.saveScreenHistory()       
        # Define new menu
        self.previousScreenName = self.screenName
        self.previousScreenType = self.screenType
        self.previousmenuKey = self.menuKey        
        self.screenType = 'menu'
        self.screenName = name
        self.menuKey = key
        self.menuList = menuList
        self.menuID = menuID
        
        # Set selected row
        self.topIndex = 0
        self.selectedRow = 0
        #check history for new menu reference
        #check if new menu screen is already in the history dictionary
        if name in self.history.keys():        
            if key == self.history[name]['menuKey']:
                self.topIndex = self.history[name]['topIndex']
                self.selectedRow = self.history[name]['selectedRow']
            
        # Store the state of the new menu in history
        self.saveScreenHistory()
        
        self.drawMenu()
        
    def drawMenu(self):
        #=======================================================================
        # drawMenu - draws the menu on the framebuffer
        #=======================================================================
        #logging.debug(str("Drawing menu"))
        self.background.fill(self.WHITE)
        self.screen.blit(self.background, (0, 0))
        
        #identify selected index of list
        self.selectedIndex=self.topIndex+self.selectedRow
        #Check if we've just scrolled above top row
        if (self.selectedRow<0):
            # Check we're not already at the start of the list.
            if self.selectedIndex>0:
                self.topIndex=self.topIndex-1
                self.selectedRow=0
                self.selectedIndex=0
            else:
                self.selectedRow=0
                self.topIndex=0
                self.selectedIndex=0
        #Check if we've just scrolled below the bottom row
        if (self.selectedRow>=self.nRows):
            #print "below bottom row"
            # Check we're not already at the end of the list.
            if self.selectedIndex<len(self.menuList):
                self.topIndex=self.topIndex+1
                self.selectedRow=self.nRows-1
            else:
                self.selectedRow=self.nRows-1
                self.selectedIndex=len(self.menuList)-1
        #Check if we've scrolled below the end of list (when the list is shorter than the number of rows displayed) 
        if self.selectedIndex>=len(self.menuList):
            self.selectedRow=self.selectedRow-1
            self.selectedIndex=self.selectedIndex-1
                
        #print self.selectedIndex
        #Loop to draw the display rows
        for n in range(self.nRows):
            # Check that menu length is not less that number of rows
            if n<len(self.menuList):
                if (n==self.selectedRow):    
                    # print self.menuList[self.topIndex+n]
                    self.drawMenuItem(n,self.menuList[self.topIndex+n],1)      
                else:
                    self.drawMenuItem(n,self.menuList[self.topIndex+n],0)
        #Should call update display here instead of after each menu item to prevent flickering.
        self.updateDisplay()    
                    
    def drawMenuItem(self,rowNumber,string,isSelected):
        #print 'string: %s' % string
        #=======================================================================
        # drawMenuItem - to be used in a loop
        #=======================================================================
        yPos=rowNumber*self.rowHeight
        #fudge factor to correct text position
        xOffset=8
        yOffset=8
        if isSelected:
            #Draw bar
            yPos=self.selectedRow*self.rowHeight    
            box = pygame.draw.rect(self.background, self.BLACK ,(0, yPos, self.background.get_width(), self.rowHeight))
            self.screen.blit(self.background, (0, 0))
            #Draw text
            text = self.font.render(string,1,self.WHITE)
        else:
            text = self.font.render(string,1,self.BLACK)
        #textPos = text.get_rect(0,0,10,10)
        #print yPos
        self.background.blit(text,(xOffset,yPos+yOffset))
        self.screen.blit(self.background, (0, 0))
        #self.updateDisplay()  
	  
        
    def drawNowPlayingScreen(self,url):
        
        self.saveScreenHistory()
        
        img_url=url
        file = StringIO.StringIO(urllib2.urlopen(img_url).read())
        #im_surf = pygame.image.load(f, "cam.jpg")
        print "file name %s" % img_url
        img = pygame.image.load(file)
        img = pygame.transform.scale(img, (self.screenHeight,self.screenHeight)) 
        
        self.background.fill(self.BLACK)
        self.screen.blit(self.background, (0, 0))
        imagerect = img.get_rect()
        #self.screen.blit(img, imagerect)
        xOffset = (self.screenWidth-self.screenHeight)/2
        self.screen.blit(img, (xOffset,0), imagerect)
                    
        self.screenName = 'nowPlaying'  
        self.screenType = 'info'
        self.updateDisplay()
    
    def drawVolumePopup(self,value):
        boxWidth=200
        boxHeight=160
        box = pygame.draw.rect(self.background, (170,170,250) ,((320-boxWidth)/2,(240-boxHeight)/2,boxWidth,boxHeight)) 
        volumeFont=pygame.font.Font(None, 200)
        text = volumeFont.render(str(value),1,self.BLACK)
        textpos = text.get_rect()
        textpos.centerx = self.background.get_rect().centerx
        textpos.centery = self.background.get_rect().centery
        self.background.blit(text,textpos)
        self.screen.blit(self.background, (0, 0))
        self.updateDisplay()    
        
    def updateDisplay(self):
        #=======================================================================
        # updateDisplay - Prepares the display and writes to the framebuffer
        #=======================================================================
        pygame.display.update()
